package com.db4o.servlet;

import java.util.*;

import javax.servlet.http.*;

import com.db4o.*;

/**
 * db4o servlet source code.
 * <br><br>Use the methods in the @link{Db4oServlet} class.
 */
class ServletFile {
    public final String i_filename;
    ObjectContainer i_objectContainer;
    ObjectServer i_objectServer;
    private final List i_sessions = new ArrayList();
    public final boolean i_shareTransaction;

    ServletFile(String filename, boolean shareTransaction) {
        i_filename = filename;
        i_shareTransaction = shareTransaction;
    }

    synchronized ObjectContainer objectContainer(HttpSession session) {
        ServletSession dbSession = null;
        boolean removedOne = false;
        ServletSession[] oldDbSessions = new ServletSession[i_sessions.size()];
        i_sessions.toArray(oldDbSessions);
        for (int i = 0; i < oldDbSessions.length; i++) {
            HttpSession oldSession = oldDbSessions[i].getSession();
            if (oldSession == null) {
                oldDbSessions[i].terminate(false);
                oldDbSessions[i] = null;
                removedOne = true;
            } else if (oldSession.getId().equals(session.getId())) {
                dbSession = oldDbSessions[i];
            }
        }
        if (removedOne) {
            i_sessions.clear();
            for (int i = 0; i < oldDbSessions.length; i++) {
            	if(oldDbSessions[i] != null){
					i_sessions.add(oldDbSessions[i]);
            	}
            }
        }
		open();
        if (dbSession == null) {
            dbSession = new ServletSession(session, this);
            i_sessions.add(dbSession);
        }
        return dbSession.objectContainer();
    }

    synchronized void sessionTerminated(ServletSession session) {
        i_sessions.remove(session);
        if (i_sessions.size() == 0) {
            close();
        }
    }

    private void open() {
        if (i_shareTransaction) {
            if (i_objectContainer != null) {
                try {
                    if (i_objectContainer.ext().isClosed()) {
                        i_objectContainer = null;
                    }
                } catch (Exception e) {
                }
            }

            if (i_objectContainer == null) {
                i_objectContainer = Db4o.openFile(i_filename);
            }
        }else{
        	if(i_objectServer == null){
        		
        		// Specifying port 0 will not open any port
        		// for remote access.
        		i_objectServer = Db4o.openServer(i_filename, 0);
        		
        	}
        }
    }

    private void close() {
        if (i_shareTransaction) {
            if (i_objectContainer != null) {
            	try{i_objectContainer.commit();} catch(Exception e){}
                while (!i_objectContainer.close());
                {
                    i_objectContainer = null;
                }
            }
        } else {
            if (i_objectServer != null) {
            	
                i_objectServer.close();
                i_objectServer = null;
            }
        }
    }

    synchronized void terminate() {
        
    	close();
        Iterator i = i_sessions.iterator();
        while (i.hasNext()) {
            ((ServletSession) i.next()).terminate(false);
        }
    }

    protected void finalize() {
        terminate();
    }
}
